package edu.scau.divineplace.service;

import cn.hutool.core.util.NumberUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.google.common.base.Preconditions;
import com.google.common.collect.Lists;
import com.google.common.collect.Sets;
import edu.scau.divineplace.entity.dos.*;
import edu.scau.divineplace.entity.enums.*;
import edu.scau.divineplace.entity.query.PageQuery;
import edu.scau.divineplace.entity.vo.commentscore.CommentScoreTotalVO;
import edu.scau.divineplace.entity.vo.content.ContentSimplyInfoVO;
import edu.scau.divineplace.entity.vo.commentscore.CommentScoreGroupVO;
import edu.scau.divineplace.entity.vo.content.ContentInfomationVO;
import edu.scau.divineplace.entity.vo.SearchResultVO;
import edu.scau.divineplace.entity.vo.content.RecentWorkVO;
import edu.scau.divineplace.mapper.ContentServiceMapper;
import edu.scau.divineplace.util.BeanConvertUtils;
import edu.scau.divineplace.util.PageQueryUtil;
import org.apache.commons.lang3.math.NumberUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.stream.Collectors;

/**
 * @Author: x1aolone
 * @Date: 2020/12/9 13:33
 */
@Service
public class ContentService {

    @Autowired
    private ImportMapperService importMapperService;

    @Autowired
    private ContentServiceMapper contentServiceMapper;

    @Autowired
    private FavoriteService favoriteService;

    @Autowired
    private CommentScoreService commentScoreService;

    @Autowired
    private RoleService roleService;


    /**
     *  通过搜索词和搜索类型获取内容列表
     * @param searchWord 搜索词
     * @param type 搜索类型
     * @param userId 已登录的用户id，可为null
     * @return
     */
    public List<SearchResultVO> search(String searchWord, Integer type, Long userId){
        ContentTypeEnum contentTypeEnum = BaseEnum.typeOf(ContentTypeEnum.class, type);
        Set<Long> ids = Sets.newHashSet();
        // 从额外信息里找id
        LambdaQueryWrapper<ContentExtraInformationDO> extraQuery = Wrappers.<ContentExtraInformationDO>lambdaQuery()
                .like(ContentExtraInformationDO::getValue, searchWord);
        importMapperService.contentExtraInformationMapper.selectList(extraQuery)
                .forEach(extraInfo -> ids.add(extraInfo.getContentId()));
        // 从music的disc里找id
        LambdaQueryWrapper<MusicDiscListDO> discQuery = Wrappers.<MusicDiscListDO>lambdaQuery()
                .like(MusicDiscListDO::getSongName, searchWord);
        importMapperService.musicDiscListMapper.selectList(discQuery)
                .forEach(discInfo -> ids.add(discInfo.getContentId()));
        // 从内容原名/内容中文名/内容介绍/刚才的id里找
        LambdaQueryWrapper<ContentBasicInformationDO> query = Wrappers.<ContentBasicInformationDO>lambdaQuery()
                .or(wrapper -> {
                        wrapper.like(ContentBasicInformationDO::getOriginalName, searchWord)
                                .or()
                                .like(ContentBasicInformationDO::getChineseName, searchWord)
                                .or()
                                .like(ContentBasicInformationDO::getIntroductionText, searchWord);
                        if (!ids.isEmpty()) {
                            wrapper.or().in(ContentBasicInformationDO::getId, ids);
                        }
                    });
        if (contentTypeEnum != null) {
            query.eq(ContentBasicInformationDO::getType, type);
        }
        List<ContentBasicInformationDO> DOS = importMapperService.contentBasicInformationMapper.selectList(query);
        List<SearchResultVO> VOS = BeanConvertUtils.BOs2VOs(DOS, SearchResultVO.class);
        // 继续填充内容
        for (SearchResultVO VO : VOS) {
            // 填充收藏数
            Integer favoriteNum = favoriteService.countFavoriteNum(null, VO.getId());
            VO.setFavoriteNum(favoriteNum);
            // 根据内容的类型，填充不同的内容
            if (VO.getType() == ContentTypeEnum.ROLE) {
                // 如果是人物，填充人物真实性
                Boolean isReal = roleService.judgeRoleTruth(VO.getId());
                VO.setIsReal(isReal);
            } else {
                // 如果是非人物，获取评分和排名
                CommentScoreTotalVO scoreTotalVO = commentScoreService.getTotalScore(VO.getId());
                Double score = commentScoreService.calcScore(scoreTotalVO.getTotalScore(), scoreTotalVO.getTotalScorePeople());
                VO.setScore(score);
                VO.setScorePeople(scoreTotalVO.getTotalScorePeople());
                // 获取排名（没做）
                VO.setRank(999);
            }
        }
        // 如果用户已登录，判断用户是否收藏了该内容
        if (userId != null) {
            for (SearchResultVO VO : VOS) {
                Boolean isFavorite = favoriteService.judge(userId, VO.getId());
                VO.setIsFavorite(isFavorite);
            }
        }
        return VOS;
    }

    /**
     * 通过内容id获取内容basic信息和extra信息
     * @param contentId
     * @return
     */
    public ContentInfomationVO getInfo (Long contentId) {
        // 通过id获取basic info
        ContentBasicInformationDO basicDO = getBasicInfo(contentId);
        // 通过id获取extra info
        List<ContentExtraInformationDO> extraDOs = getExtraInfo(contentId);
        ContentInfomationVO VO = ContentInfomationVO.builder()
                .basicInfo(basicDO)
                .extraInfoList(extraDOs)
                .build();
        return VO;
    }

    /**
     * 通过内容id获取内容basic信息
     * @param contentId
     * @return
     */
    public ContentBasicInformationDO getBasicInfo (Long contentId) {
        // 通过id获取basic info
        ContentBasicInformationDO basicDO = importMapperService.contentBasicInformationMapper.selectById(contentId);
        return basicDO;
    }

    /**
     * 通过内容id获取内容extra信息
     * @param contentId
     * @return
     */
    public List<ContentExtraInformationDO> getExtraInfo (Long contentId) {
        // 通过id获取extra info
        LambdaQueryWrapper<ContentExtraInformationDO> extraQuery = Wrappers.<ContentExtraInformationDO>lambdaQuery()
                .eq(ContentExtraInformationDO::getContentId, contentId);
        List<ContentExtraInformationDO> extraDOs = importMapperService.contentExtraInformationMapper.selectList(extraQuery);
        return extraDOs;
    }

    /**
     * 通过内容类型获取内容的排行榜，分页
     * @param contentType
     * @param pageQuery
     * @return
     */
    public List<ContentSimplyInfoVO> listRankContent (PageQuery pageQuery, Integer contentType){
        PageQueryUtil.fillAllIfAbsent(pageQuery);
        // 专门写个实体类接收吧
        Page<ContentSimplyInfoVO> contentPage = new Page<>(pageQuery.getCurrentPage(), pageQuery.getPageSize());
        List<ContentSimplyInfoVO> VOS = contentServiceMapper.selectRankContent(contentPage, contentType).getRecords();
        return VOS;
    }

    /**
     * 通过内容类型获取最近更新的内容列表
     * @param contentType
     * @param pageQuery
     * @return
     */
    public List<ContentSimplyInfoVO> listRecentContent (PageQuery pageQuery, Integer contentType){
        PageQueryUtil.fillAllIfAbsent(pageQuery);
        Page<ContentSimplyInfoVO> contentPage = new Page<>(pageQuery.getCurrentPage(), pageQuery.getPageSize());
        List<ContentSimplyInfoVO> VOS = contentServiceMapper.selectRecentContent(contentPage, contentType).getRecords();
        return VOS;
    }

    /**
     * 通过真人id获取参与的内容的基本信息
     * @param roleId
     * @return
     */
    public List<RecentWorkVO> listRecentWork (PageQuery pageQuery, Long roleId, Long userId) {
        // roleId = 13, 出问题了, 有一些返回的数据是没有basicInfo的
        PageQueryUtil.fillAllIfAbsent(pageQuery);
        List<RecentWorkVO> VOS = Lists.newArrayList();
        // 获取人物为制作者的内容id和人物的参与类型，根据内容排序，同一个内容的关系会连在一起
        Page<ContentRoleRelationDO> relationPage = new Page<>(pageQuery.getCurrentPage(), pageQuery.getPageSize());
        LambdaQueryWrapper<ContentRoleRelationDO> relationQuery = Wrappers.<ContentRoleRelationDO>lambdaQuery()
                .select(ContentRoleRelationDO::getContentId)
                .eq(ContentRoleRelationDO::getRoleId, roleId)
                .eq(ContentRoleRelationDO::getRoleType, RoleTypeEnum.PRODUCER)
                .groupBy(ContentRoleRelationDO::getContentId)
                .groupBy(ContentRoleRelationDO::getUpdateTime)
                .groupBy(ContentRoleRelationDO::getCreateTime)
                .orderByDesc(ContentRoleRelationDO::getUpdateTime)
                .orderByDesc(ContentRoleRelationDO::getCreateTime);
        relationPage = importMapperService.contentRoleRelationMapper.selectPage(relationPage, relationQuery);
        for (ContentRoleRelationDO relationDO : relationPage.getRecords()) {
            Long contentId = relationDO.getContentId();
            System.err.println(contentId);
            // 获取内容的信息
            ContentBasicInformationDO basicInfo = importMapperService.contentBasicInformationMapper.selectById(contentId);
            // 获取人物在该内容中担任的职位
            LambdaQueryWrapper<ContentRoleRelationDO> roleTypeQuery = Wrappers.<ContentRoleRelationDO>lambdaQuery()
                    .eq(ContentRoleRelationDO::getContentId, contentId)
                    .eq(ContentRoleRelationDO::getRoleId, roleId)
                    .eq(ContentRoleRelationDO::getRoleType, RoleTypeEnum.PRODUCER);
            List<ContentRoleRelationDO> roleTypeDOS = importMapperService.contentRoleRelationMapper.selectList(roleTypeQuery);
            List<String> roleTypes = roleTypeDOS.stream().map(ContentRoleRelationDO::getRoleTypeDetail).collect(Collectors.toList());
            // 获取内容评分
            CommentScoreTotalVO scoreTotalVO = commentScoreService.getTotalScore(contentId);
            Double score = commentScoreService.calcScore(scoreTotalVO.getTotalScore(), scoreTotalVO.getTotalScorePeople());
            Integer scorePeople = scoreTotalVO.getTotalScorePeople();
            // 获取用户是否收藏
            Boolean isFavorite = favoriteService.judge(userId, contentId);
            RecentWorkVO VO = RecentWorkVO.builder()
                    .basicInfo(basicInfo)
                    .roleTypeDetails(roleTypes)
                    .score(score)
                    .scorePeople(scorePeople)
                    .isFavorite(isFavorite)
                    .build();
            VOS.add(VO);
        }
        return VOS;
    }



}
